/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools resize load
 */

#include "resize_load.h"

#include <clocale>
#include <cstdbool>
#include <ctime>

#include "constant.h"
#include "device_manager.h"
#include "hmfs_common.h"
#include "load_check_point.h"
#include "load_nat.h"
#include "load_sit.h"
#include "load_super_block.h"
#include "node.h"

namespace OHOS {
namespace Hmfs {
ResizeLoad::ResizeLoad(std::shared_ptr<HmfsConfigData> &configData, std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo)
    : config_(configData), superBlockInfo_(superBlockInfo)
{
}

void ResizeLoad::InitSuperBlockInfo()
{
    HMFS_DEBUG("Enter InitSuperBlockInfo");
    InitializeSuperBlockParameters();
    InitializeDevicePaths();
    InitializeDeviceSegments();
    InitializeZonedModel();
    InitializeSingleDevice();
    LogSuperBlockInfo();
}

void ResizeLoad::InitializeSuperBlockParameters()
{
    SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
    superBlockInfo_->log2SectorsPerBlock = GetLeValue(superBlockData->log2SectorsPerBlock);
    superBlockInfo_->logBlockSize = GetLeValue(superBlockData->logBlockSize);
    superBlockInfo_->blockSize = 1 << superBlockInfo_->logBlockSize;
    superBlockInfo_->logBlksPerSeg = GetLeValue(superBlockData->logBlksPerSeg);
    superBlockInfo_->blocksPerSeg = 1 << superBlockInfo_->logBlksPerSeg;
    superBlockInfo_->segmentsPerSection = GetLeValue(superBlockData->segsPerSection);
    superBlockInfo_->sectionsPerZone = GetLeValue(superBlockData->sectionsPerZone);
    superBlockInfo_->totalSections = GetLeValue(superBlockData->sectionCount);
    constexpr uint32_t segmentCountInNAT = 2;
    superBlockInfo_->totalNodeCount = (GetLeValue(superBlockData->segmentCountInNAT) / segmentCountInNAT) *
        superBlockInfo_->blocksPerSeg * NAT_ENTRY_PER_BLOCK;
    superBlockInfo_->rootInodeId = GetLeValue(superBlockData->rootInodeId);
    superBlockInfo_->nodeInodeId = GetLeValue(superBlockData->nodeInodeId);
    superBlockInfo_->metaInodeId = GetLeValue(superBlockData->metaInodeId);
    superBlockInfo_->curVictimSec = NULL_SEGNO;
}

void ResizeLoad::InitializeDevicePaths()
{
    SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
    for (int32_t i = 0; i < MAX_DEVICE_COUNT; i++) {
        if (!superBlockData->devices[i].path[0]) {
            break;
        }
        if (i != 0) {
            config_->devices[i].path = superBlockData->devices[i].path;
        } else {
            HMFS_ASSERT(!strcmp((char *)superBlockData->devices[i].path, config_->devices[i].path.c_str()));
        }
    }
}

void ResizeLoad::InitializeDeviceSegments()
{
    SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
    for (int32_t i = 0; i < MAX_DEVICE_COUNT; i++) {
        config_->devices[i].segmentCount = LE32ToNative(superBlockData->devices[i].segmentCount);
        if (i != 0) {
            config_->devices[i].startBlockId = config_->devices[i - 1].endBlockId + 1;
        }
        config_->devices[i].endBlockId = config_->devices[i].startBlockId + config_->devices[i].segmentCount *
            config_->segmentBlockCount - 1;
        if (i == 0) {
            config_->devices[i].endBlockId += GetLeValue(superBlockData->segment0BlockId);
        }
    }
}

void ResizeLoad::InitializeZonedModel()
{
    for (int32_t i = 0; i < MAX_DEVICE_COUNT; i++) {
        if (config_->zonedModel == HMFS_ZONED_NONE) {
            if (config_->devices[i].zonedModel == HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HM;
            } else if (config_->devices[i].zonedModel == HMFS_ZONED_HA && config_->zonedModel != HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HA;
            }
        }
    }
}

void ResizeLoad::InitializeSingleDevice()
{
    if (DeviceManager::GetInstance().GetDeviceCount() == 1) {
        DeviceInfo *deviceInfo = DeviceManager::GetInstance().GetDeviceInfo(0);
        SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
        config_->devices[0].segmentCount = LE32ToNative(superBlockData->segmentCount);
        deviceInfo->segmentCount = LE32ToNative(superBlockData->segmentCount);
        config_->devices[0].endBlockId = config_->devices[0].startBlockId +
            config_->devices[0].segmentCount * config_->segmentBlockCount - 1;
        config_->devices[0].endBlockId += GetLeValue(superBlockData->segment0BlockId);
        deviceInfo->endBlockId = config_->devices[0].endBlockId;
        if (config_->zonedModel == HMFS_ZONED_NONE) {
            if (deviceInfo->zonedModel == HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HM;
            } else if (deviceInfo->zonedModel == HMFS_ZONED_HA && config_->zonedModel != HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HA;
            }
        }
    }
}

void ResizeLoad::LogSuperBlockInfo()
{
    SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
    uint64_t totalSectors = GetLeValue(superBlockData->blockCount) << superBlockInfo_->log2SectorsPerBlock;
    HMFS_INFO("Segments per section = %d", superBlockInfo_->segmentsPerSection);
    HMFS_INFO("Sections per zone = %d", superBlockInfo_->sectionsPerZone);
    HMFS_INFO("total FS sectors = %" PRIu64" (%" PRIu64" MB)",
        totalSectors, totalSectors >> (MB_SHIFT - GetLeValue(superBlockData->logSectorSize)));
}

int32_t ResizeLoad::HmfsShouldProceed(SuperBlockData *superBlockData, uint32_t flag)
{
    HMFS_CHECK_ONLY_EXPER(superBlockData != nullptr, return EXIT_ERR_CODE);
    HMFS_DEBUG("Enter HmfsShouldProceed");
    if (!config_->fixOn && (config_->autoFix || config_->preenMode)) {
        if ((flag & CP_FLAG_FSCK) || (flag & CP_FLAG_QUOTA_NEED_FSCK) || (config_->abnormalStop) ||
            (config_->hmfsErrors) || (HasQuotaInode(superBlockData) && (flag & CP_FLAG_ERROR))) {
            config_->fixOn = 1;
        } else if (!config_->preenMode) {
            return EXIT_ERR_CODE;
        }
    }
    return SUCCESS_CODE;
}

int32_t ResizeLoad::UpdateSbFeatures()
{
    SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
    int32_t superBlockIsChanged = 0;
    if (!(superBlockData->features & NativeToLE32(HMFS_FEATURE_ENCRYPT)) &&
        (config_->feature & NativeToLE32(HMFS_FEATURE_ENCRYPT))) {
        superBlockData->features |= NativeToLE32(HMFS_FEATURE_ENCRYPT);
        HMFS_INFO("Set Encryption feature");
        superBlockIsChanged = 1;
    }
    if (!(superBlockData->features & NativeToLE32(HMFS_FEATURE_CASEFOLD)) &&
        config_->feature & NativeToLE32(HMFS_FEATURE_CASEFOLD)) {
        if (!config_->encoding) {
            HMFS_ERROR("ERROR: Must specify encoding to enable casefolding.");
            return EXIT_ERR_CODE;
        }
        superBlockData->features |= NativeToLE32(HMFS_FEATURE_CASEFOLD);
        HMFS_INFO("Set Casefold feature");
        superBlockIsChanged = 1;
    }

    config_->feature = superBlockData->features;
    if (!superBlockIsChanged) {
        return SUCCESS_CODE;
    }
    UpdateSuperBlock(superBlockData, SUPER_BLOCK_MASK_ALL);
    return SUCCESS_CODE;
}

void *ResizeLoad::GetBitmapPtr(uint32_t flag)
{
    if (superBlockInfo_ == nullptr) {
        return nullptr;
    }
    CheckPointData *checkPointData = superBlockInfo_->checkPointData;
    SuperBlockData *superBlockData = superBlockInfo_->rawSuper;
    int32_t offset = 0;
    if (IsSetCkptFlags(checkPointData, CP_FLAG_LARGE_NAT_BITMAP)) {
        uint32_t chksumSize = 0;
        offset = (flag == static_cast<uint32_t>(BitmapType::SIT_BITMAP)) ?
            LE32ToNative(checkPointData->natVersionBitmapSize) : 0;
        if (LE32ToNative(checkPointData->checksumOffset) == CP_MIN_CHECKSUM_OFFSET) {
            chksumSize = sizeof(uint32_t);
        }
        return &checkPointData->sitNatVersionBitmap[offset + chksumSize];
    }
    if (LE32ToNative(superBlockData->checkPointPayload) > 0) {
        if (flag == static_cast<uint32_t>(BitmapType::NAT_BITMAP)) {
            return &checkPointData->sitNatVersionBitmap;
        } else {
            return ((char *)checkPointData + HMFS_BLOCK_SIZE);
        }
    } else {
        offset = (flag == static_cast<uint32_t>(BitmapType::NAT_BITMAP)) ?
            LE32ToNative(checkPointData->sitVersionBitmapSize) : 0;
        return &checkPointData->sitNatVersionBitmap[offset];
    }
}

uint32_t ResizeLoad::GetStartCpAddr()
{
    uint32_t startCpAddr = LE32ToNative(superBlockInfo_->rawSuper->checkPointBlockId);
    if (superBlockInfo_->currentCheckPointId == CHECKPOINT_TWO) {
        startCpAddr += superBlockInfo_->blocksPerSeg;
    }
    return startCpAddr;
}

uint32_t ResizeLoad::GetNextFreeBlockAddr(CurrentSegmentInfo *currentSegment)
{
    if (currentSegment == nullptr) {
        return 0;
    }
    uint32_t segmentNumber = currentSegment->segmentNumber;
    return superBlockInfo_->segmentTable->mainBlockAddr + (segmentNumber << superBlockInfo_->logBlksPerSeg) +
        currentSegment->nextBlockOffset;
}

bool ResizeLoad::HmfsIsValidBlockAddr(uint32_t blockAddr, int32_t type)
{
    switch (type) {
        case static_cast<int32_t>(MetaType::META_NAT):
            break;
        case static_cast<int32_t>(MetaType::META_SIT): {
            if (blockAddr >= SIT_BLK_CNT(superBlockInfo_)) {
                return false;
            }
            break;
        }
        case static_cast<int32_t>(MetaType::META_SSA): {
            if (blockAddr >= MAIN_BLOCKK_ADDR(superBlockInfo_) || blockAddr <
                superBlockInfo_->segmentTable->ssaBlockAddr)  {
                return false;
            }
            break;
        }
        case static_cast<int32_t>(MetaType::META_CP): {
            if (blockAddr >= superBlockInfo_->segmentTable->sitInfo->sitBaseAddr || blockAddr < GetStartCpAddr()) {
                return false;
            }
            break;
        }
        case static_cast<int32_t>(MetaType::META_POR): {
            if (blockAddr >= MAX_BLOCK_ADDR(superBlockInfo_) || blockAddr < MAIN_BLOCKK_ADDR(superBlockInfo_)) {
                return false;
            }
            break;
        }
        default: {
            HMFS_ASSERT(false);
            break;
        }
    }
    return true;
}

FsyncInodeEntry *ResizeLoad::GetFsyncInode(struct ListNode *head, uint32_t inodeNumber)
{
    if (head == nullptr) {
        return nullptr;
    }
    FsyncInodeEntry *entry = nullptr;
    LIST_FOR_EACH_ENTRY(entry, head, FsyncInodeEntry, list) {
        if (entry->inodeNumber == inodeNumber) {
            return entry;
        }
    }
    return nullptr;
}

FsyncInodeEntry *ResizeLoad::AddFsyncinode(struct ListNode *head, uint32_t inodeNumber)
{
    if (head == nullptr) {
        return nullptr;
    }
    FsyncInodeEntry *entry = static_cast<FsyncInodeEntry *>(calloc(sizeof(FsyncInodeEntry), 1));
    if (entry == nullptr) {
        return nullptr;
    }
    entry->inodeNumber = inodeNumber;
    ListTailInsert(head, &entry->list);
    return entry;
}

int32_t ResizeLoad::FindFsyncInode(struct ListNode *head)
{
    HMFS_CHECK_ONLY_EXPER(head != nullptr, return EXIT_ERR_CODE);
    SegmentInfoTable *segmentInfoTable = superBlockInfo_->segmentTable;
    uint32_t freeBlocks = segmentInfoTable->mainSegments * superBlockInfo_->blocksPerSeg -
        superBlockInfo_->totalValidBlockCount;
    CurrentSegmentInfo *currentSegment = reinterpret_cast<CurrentSegmentInfo *>(
        segmentInfoTable->currentSegmentArray + CURSEG_NODE_WARM);
    uint32_t blockAddr = GetNextFreeBlockAddr(currentSegment);
    NodeData *nodeBlock = static_cast<NodeData *>(calloc(HMFS_BLOCK_SIZE, 1));
    HMFS_ASSERT(nodeBlock);
    int32_t ret = 0;
    uint32_t loopCount = 0;
    while (1) {
        if (!HmfsIsValidBlockAddr(blockAddr, static_cast<int32_t>(MetaType::META_POR))) {
            break;
        }
        ret = HmfsIo::GetInstance().DevReadBlock(nodeBlock, blockAddr);
        if (ret) {
            break;
        }
        if (!IsRecoverableDnode(superBlockInfo_, nodeBlock)) {
            break;
        }
        ret = ProcessNodeBlock(head, nodeBlock, blockAddr, loopCount, freeBlocks);
        if (ret != SUCCESS_CODE) {
            break;
        }
        blockAddr = nodeBlock->footer.nextBlockAddr;
    }
    free(nodeBlock);
    return ret;
}

int32_t ResizeLoad::ProcessNodeBlock(struct ListNode *head, NodeData *nodeBlock, uint32_t blockAddr,
    uint32_t &loopCount, uint32_t freeBlocks)
{
    HMFS_CHECK_ONLY_EXPER(nodeBlock != nullptr, return EXIT_ERR_CODE);
    if (IsNode(nodeBlock, FSYNC_BIT_SHIFT) == 0) {
        if (++loopCount >= freeBlocks || blockAddr == nodeBlock->footer.nextBlockAddr) {
            HMFS_ERROR("detect looped node chain, blockAddr");
            return EXIT_ERR_CODE;
        }
        return SUCCESS_CODE;
    }
    FsyncInodeEntry *entry = GetFsyncInode(head, nodeBlock->footer.inodeNumber);
    if (entry == nullptr) {
        entry = AddFsyncinode(head, nodeBlock->footer.inodeNumber);
        if (entry == nullptr) {
            return EXIT_ERR_CODE;
        }
    }
    entry->blockAddr = blockAddr;
    if (IsInode(nodeBlock) && IsNode(nodeBlock, DENT_BIT_SHIFT)) {
        entry->lastDentry = blockAddr;
    }
    if (++loopCount >= freeBlocks || blockAddr == nodeBlock->footer.nextBlockAddr) {
        HMFS_ERROR("detect looped node chain, blockAddr:%u, next:%u", blockAddr, nodeBlock->footer.nextBlockAddr);
        return EXIT_ERR_CODE;
    }
    return SUCCESS_CODE;
}

int32_t ResizeLoad::HmfsRaMetaPages(uint32_t start, int32_t numPages, int32_t type)
{
    uint32_t currentBlock = start;
    uint32_t blockAddr = 0;
    uint32_t startBlock = 0;
    uint32_t len = 0;
    for (; numPages-- > 0; currentBlock++) {
        if (!HmfsIsValidBlockAddr(currentBlock, type)) {
            break;
        }
        switch (type) {
            case static_cast<int32_t>(MetaType::META_NAT):
                if (currentBlock >= NatBlockOffset(superBlockInfo_->nodeAddrTable->maxNodeId)) {
                    currentBlock = 0;
                }
                blockAddr = CurrentNatAddr(superBlockInfo_, currentBlock * NAT_ENTRY_PER_BLOCK);
                break;
            case static_cast<int32_t>(MetaType::META_SIT):
                blockAddr = CurrentSitAddr(superBlockInfo_, currentBlock * SIT_ENTRIES_PER_BLOCK);
                break;
            case static_cast<int32_t>(MetaType::META_SSA):
            case static_cast<int32_t>(MetaType::META_CP):
            case static_cast<int32_t>(MetaType::META_POR):
                blockAddr = currentBlock;
                break;
            default:
                HMFS_ASSERT(0);
        }

        if (len == 0) {
            startBlock = blockAddr;
            len = 1;
        } else if (startBlock + len == blockAddr) {
            len++;
        } else {
            HmfsIo::GetInstance().DevReadAhead(startBlock << HMFS_BLKSIZE_BITS);
        }
    }
    if (len) {
        HmfsIo::GetInstance().DevReadAhead(startBlock << HMFS_BLKSIZE_BITS);
    }
    return currentBlock - start;
}

int32_t ResizeLoad::DoRecordFsyncData(NodeData *nodeBlock, uint32_t blockAddr)
{
    HMFS_CHECK_ONLY_EXPER(nodeBlock != nullptr, return EXIT_ERR_CODE);
    uint32_t sitNumber = GetSegmentNumber(superBlockInfo_, blockAddr);
    SegmentEntry *sitEntry = GetSegEntry(superBlockInfo_, sitNumber);
    HMFS_CHECK_ONLY_EXPER(sitEntry != nullptr, return EXIT_ERR_CODE);
    uint32_t offset = OffsetInSegment(superBlockInfo_, blockAddr);
    if (HmfsCommon::GetInstance().VerifyBit(offset, sitEntry->currentValidBitmap)) {
        HMFS_ASSERT(0);
        return EXIT_ERR_CODE;
    }
    if (HmfsCommon::GetInstance().VerifyBit(offset, sitEntry->checkpointValidBitmap)) {
        HMFS_ASSERT(0);
        return EXIT_ERR_CODE;
    }

    if (sitEntry->checkPointValidBlocks == 0) {
        sitEntry->checkPointType = CURSEG_NODE_WARM;
    }
    sitEntry->checkPointValidBlocks++;
    HmfsCommon::GetInstance().SetBit(offset, sitEntry->checkpointValidBitmap);

    HMFS_INFO("do_record_fsync_data: [node] inodeNumber = %u, nodeId = %u, blockAddr = %u",
        nodeBlock->footer.inodeNumber, nodeBlock->footer.flag, blockAddr);
    if ((IsInode(nodeBlock) != SUCCESS_CODE) && (nodeBlock->inode.inlineFlags &
        static_cast<uint8_t>(HmfsExtType::HMFS_INLINE_DATA))) {
        return SUCCESS_CODE;
    }
    if (OfsOfNode(nodeBlock) == XATTR_NODE_OFFSET) {
        return SUCCESS_CODE;
    }

    return ProcessDataBlocks(nodeBlock, blockAddr);
}

int32_t ResizeLoad::ProcessDataBlocks(NodeData *nodeBlock, uint32_t blockAddr)
{
    HMFS_CHECK_ONLY_EXPER(nodeBlock != nullptr, return EXIT_ERR_CODE);
    uint32_t start = CalculateBlockIndex(OfsOfNode(nodeBlock), nodeBlock);
    uint32_t end = start + GetAddressesPerPage(superBlockInfo_, nodeBlock, nullptr);
    uint32_t nodeBlockOffset = 0;
    int32_t ret = 0;
    int32_t recorded = 0;
    for (; start < end; start++, nodeBlockOffset++) {
        blockAddr = DatablockAddr(nodeBlock, nodeBlockOffset);
        if (!IsValidDataBlkAddr(blockAddr)) {
            continue;
        }
        if (!HmfsIsValidBlockAddr(blockAddr, static_cast<int32_t>(MetaType::META_POR))) {
            ret = EXIT_ERR_CODE;
            HMFS_ERROR("It is invalid blockAddr!");
            return ret;
        }

        uint32_t sitNumber = GetSegmentNumber(superBlockInfo_, blockAddr);
        SegmentEntry *sitEntry = GetSegEntry(superBlockInfo_, sitNumber);
        uint32_t offset = OffsetInSegment(superBlockInfo_, blockAddr);
        if (HmfsCommon::GetInstance().VerifyBit(offset, sitEntry->currentValidBitmap)) {
            continue;
        }
        if (HmfsCommon::GetInstance().VerifyBit(offset, sitEntry->checkpointValidBitmap)) {
            continue;
        }
        if (sitEntry->checkPointValidBlocks == 0) {
            sitEntry->checkPointType = CURSEG_DATA_WARM;
        }
        sitEntry->checkPointValidBlocks++;
        HmfsCommon::GetInstance().SetBit(offset, sitEntry->checkpointValidBitmap);
        HMFS_INFO("do_record_fsync_data: [data] inodeNumber = %u, nodeId = %u, blockAddr = %u",
            nodeBlock->footer.inodeNumber, OfsOfNode(nodeBlock), blockAddr);
        recorded++;
    }

    HMFS_INFO("recoverData: inodeNumber = %u, nodeId = %u, recorded = %d, ret = %d",
        nodeBlock->footer.inodeNumber, OfsOfNode(nodeBlock), recorded, ret);
    return ret;
}

void ResizeLoad::DelFsyncInode(FsyncInodeEntry *entry)
{
    HMFS_CHECK_ONLY_EXPER(entry != nullptr, return);
    ListDelete(&entry->list);
    free(entry);
}

int32_t ResizeLoad::TraverseDnodes(struct ListNode *inodeList)
{
    HMFS_CHECK_ONLY_EXPER(inodeList != nullptr, return EXIT_ERR_CODE);
    CurrentSegmentInfo *currentSegment = GetCurrentSegment(superBlockInfo_, CURSEG_NODE_WARM);
    uint32_t blockAddr = NEXT_FREE_BLKADDR(superBlockInfo_, currentSegment);
    NodeData *nodeBlock = static_cast<NodeData *>(calloc(HMFS_BLOCK_SIZE, 1));
    HMFS_ASSERT(nodeBlock);
    int32_t ret = 0;
    while (1) {
        if (!HmfsIsValidBlockAddr(blockAddr, static_cast<int32_t>(MetaType::META_POR))) {
            break;
        }
        ret = HmfsIo::GetInstance().DevReadBlock(nodeBlock, blockAddr);
        if (ret) {
            break;
        }
        if (!IsRecoverableDnode(superBlockInfo_, nodeBlock)) {
            break;
        }
        FsyncInodeEntry *entry = GetFsyncInode(inodeList, nodeBlock->footer.inodeNumber);
        if (!entry) {
            blockAddr = nodeBlock->footer.nextBlockAddr;
            continue;
        }
        ret = DoRecordFsyncData(nodeBlock, blockAddr);
        if (ret) {
            break;
        }
        if (entry->blockAddr == blockAddr) {
            DelFsyncInode(entry);
        }
        blockAddr = nodeBlock->footer.nextBlockAddr;
    }
    free(nodeBlock);
    return ret;
}

void ResizeLoad::DestroyFsyncDnodes(ListNode *head)
{
    HMFS_CHECK_ONLY_EXPER(head != nullptr, return);
    FsyncInodeEntry *entry = nullptr;
    FsyncInodeEntry *tmp = nullptr;
    LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, head, FsyncInodeEntry, list) {
        DelFsyncInode(entry);
    }
}

int32_t ResizeLoad::RecordFsyncData(LoadSit &loadSit)
{
    HMFS_DEBUG("Enter RecordFsyncData");
    ListNode iNodeList = { &iNodeList, &iNodeList };
    if (!NeedFsyncDataRecord(superBlockInfo_, config_)) {
        return SUCCESS_CODE;
    }
    int32_t ret = FindFsyncInode(&iNodeList);
    if (ret) {
        HMFS_ERROR("Failed to find fsync inode");
        DestroyFsyncDnodes(&iNodeList);
        return ret;
    }

    ret = loadSit.LateBuildSegmentManager();
    if (ret != SUCCESS_CODE) {
        HMFS_ERROR("Failed to build segment manager");
        DestroyFsyncDnodes(&iNodeList);
        return ret;
    }
    ret = TraverseDnodes(&iNodeList);
    DestroyFsyncDnodes(&iNodeList);
    return ret;
}

int32_t ResizeLoad::HmfsLoadData()
{
    HMFS_CHECK_ONLY_EXPER(superBlockInfo_ != nullptr, return EXIT_ERR_CODE);
    HMFS_DEBUG("Enter HmfsLoadData");

    superBlockInfo_->activeLogs = CURSEG_TYPE_MAX;
    LoadSuperBlock loadSb(this);
    HMFS_CHECK_ONLY_EXPER(loadSb.HmfsLoadSuperBlockData() == SUCCESS_CODE, return EXIT_ERR_CODE);
    InitSuperBlockInfo();
    LoadCheckPoint loadCp(this);
    HMFS_CHECK_ONLY_EXPER(loadCp.HmfsLoadCpData() == SUCCESS_CODE, return EXIT_ERR_CODE);

    CheckPointData *checkPointData = superBlockInfo_->checkPointData;
    if (config_->quotaFix && (GetLeValue(checkPointData->checkPointFlags) & CP_FLAG_QUOTA_NEED_FSCK)) {
        config_->fixOn = 1;
    }

    if (config_->layout) {
        return CONFIG_LAYOUT;
    }

    if (UpdateSbFeatures() != SUCCESS_CODE) {
        HMFS_ERROR("Failed to update superblock features");
        return EXIT_ERR_CODE;
    }

    if (config_->feature & NativeToLE32(HMFS_FEATURE_INODE_CHKSUM)) {
        config_->checksumSeed = HmfsCommon::GetInstance().CalculateCrc32(~0,
            superBlockInfo_->rawSuper->uuid, sizeof(superBlockInfo_->rawSuper->uuid));
    }

    superBlockInfo_->totalValidNodeCount = GetLeValue(checkPointData->validNodeCount);
    superBlockInfo_->totalValidInodeCount = GetLeValue(checkPointData->validInodeCount);
    superBlockInfo_->userBlockCount = GetLeValue(checkPointData->userBlockCount);
    superBlockInfo_->totalValidBlockCount = GetLeValue(checkPointData->validBlockCount);
    superBlockInfo_->lastValidBlockCount = superBlockInfo_->totalValidBlockCount;
    superBlockInfo_->allocValidBlockCount = 0;

    LoadSit loadSit(this);
    LoadNat loadNat(this);
    if (loadSit.BuildSegmentBegin() != SUCCESS_CODE || loadNat.BuildNodeManager() != SUCCESS_CODE ||
        RecordFsyncData(loadSit) != SUCCESS_CODE ||
        HmfsShouldProceed(superBlockInfo_->rawSuper, GetLeValue(checkPointData->checkPointFlags)) != SUCCESS_CODE ||
        loadSit.LateBuildSegmentManager() != SUCCESS_CODE || loadNat.HmfsLateInitNidBitmap() != SUCCESS_CODE) {
        HMFS_ERROR("Failed during HmfsLoadData process");
        return EXIT_ERR_CODE;
    }
    return SUCCESS_CODE;
}

std::shared_ptr<HmfsConfigData> ResizeLoad::GetConfig()
{
    return config_;
}

std::shared_ptr<HmfsSuperBlockInfo> ResizeLoad::GetSuperBlockInfo()
{
    return superBlockInfo_;
}
} // namespace Hmfs
} // namespace OHOS